/*使用工具类模块*/

#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
#include <jsoncpp/json/json.h>
#include <mysql/mysql.h>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

#include "log.hpp"

typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

namespace ns_util
{
    using namespace ns_log;
    class json_util
    {
    public:
        static bool serialize(const Json::Value &root, std::string &str)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            std::stringstream ss;
            int ret = sw->write(root, &ss);
            if (ret != 0)
            {
                LOG(ERROE) << "json serialize failed!!" << "\n";
                return false;
            }
            str = ss.str();
            return true;
        }

        static bool unserialize(const std::string &str, Json::Value &root)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string err;
            bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
            if (ret == false)
            {
                LOG(ERROR) << "json unserialize failed:" << err.c_str() << std::endl;
                return false;
            }
            return true;
        }
    };

    class mysql_util
    {
    public:
        // 创建mysql连接
        static MYSQL *mysql_create(const std::string &host,
                                   const std::string &user,
                                   const std::string &pass,
                                   const std::string &db_name,
                                   uint16_t port)
        {
            // 初始化mysql句柄
            MYSQL *mysql = mysql_init(nullptr);
            if (mysql == nullptr)
            {
                LOG(ERROR) << "Init mysql instance failed!" << "\n";
                return nullptr;
            }

            // 连接mysql服务
            if (mysql_real_connect(mysql, host.c_str(), user.c_str(), pass.c_str(), db_name.c_str(), port, nullptr, 0) == nullptr)
            {
                LOG(FATAL) << "Connect mysql server failed!" << "\n";
                LOG(FATAL) << mysql_error(mysql) << "\n";
                mysql_close(mysql);
                return nullptr;
            }

            // 设置字符集为utf-8
            mysql_set_character_set(mysql, "uft8");
            return mysql;
        }

        // 关闭mysql连接
        static void mysql_destory(MYSQL *mysql)
        {
            if (mysql != nullptr)
            {
                mysql_close(mysql);
            }
            return;
        }

        // 执⾏sql语句
        static bool mysql_exec(MYSQL *mysql, const std::string &sql)
        {
            int ret = mysql_query(mysql, sql.c_str());
            if (ret != 0)
            {
                LOG(ERROR) << "SQL:" << sql << "\n";
                LOG(ERROR) << "ERROR:" << mysql_error(mysql) << "\n";
                return false;
            }
            return true;
        }
    };

    class string_util
    {
    public:
        static int split(const std::string &in, const std::string &sep, std::vector<std::string> &arry)
        {
            arry.clear();
            size_t pos, idx = 0;
            while (idx < in.size())
            {
                pos = in.find(sep, idx);
                if (pos == std::string::npos)
                {
                    arry.push_back(in.substr(idx));
                    break;
                }
                if (pos != idx)
                {
                    arry.push_back(in.substr(idx, pos - idx));
                }
                idx = pos + sep.size();
            }
            return arry.size();
        }
    };

    class file_util
    {
    public:
        static bool read(const std::string &filename, std::string &body)
        {
            std::ifstream file;
            //打开文件
            file.open(filename.c_str(),std::ios::in | std::ios::binary);
            if(!file)
            {
                LOG(ERROR) << filename << "Open failed!\n";
                return false;
            }
            // 计算⽂件⼤⼩
            file.seekg(0,std::ios::end);
            body.resize(file.tellg());
            file.seekg(0,std::ios::beg);
            file.read(&body[0],body.size());
            if(file.good() == false)
            {
                LOG(ERROR) << filename << " Read failed!" << std::endl;
                file.close();
                return false;
            }
            file.close();
            return true;
        }
    };
}